package com.huawei.zyb.taskManager.infrastructure.persistence.repository;

import com.huawei.zyb.taskManager.domain.requirement.entity.Requirement;
import com.huawei.zyb.taskManager.domain.requirement.repository.RequirementRepository;
import com.huawei.zyb.taskManager.domain.requirement.valueobject.*;
import com.huawei.zyb.taskManager.domain.developer.valueobject.DeveloperId;
import com.huawei.zyb.taskManager.domain.project.valueobject.ProjectId;
import com.huawei.zyb.taskManager.infrastructure.persistence.mapper.RequirementMapper;
import com.huawei.zyb.taskManager.infrastructure.persistence.po.RequirementPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 需求仓储实现
 */
@Repository
public class RequirementRepositoryImpl implements RequirementRepository {
    
    @Autowired
    private RequirementMapper requirementMapper;
    
    @Override
    public Requirement save(Requirement requirement) {
        RequirementPO requirementPO = toRequirementPO(requirement);
        if (requirementPO.getId() == null) {
            requirementMapper.insert(requirementPO);
            // 重新创建带有数据库生成ID的需求对象
            if (requirementPO.getId() != null) {
                return Requirement.restore(
                    RequirementId.of(requirementPO.getId()),
                    requirement.getTitle(),
                    requirement.getDescription(),
                    requirement.getStatus(),
                    requirement.getPriority(),
                    requirement.getProjectId(),
                    requirement.getOwnerId(),
                    requirement.getExpectedCompletionDate(),
                    requirement.getCreatedAt(),
                    requirement.getUpdatedAt()
                );
            }
        } else {
            requirementMapper.update(requirementPO);
        }
        return requirement;
    }
    
    @Override
    public Optional<Requirement> findById(RequirementId requirementId) {
        RequirementPO requirementPO = requirementMapper.findById(requirementId.getValue());
        return requirementPO != null ? Optional.of(toRequirement(requirementPO)) : Optional.empty();
    }
    
    @Override
    public List<Requirement> findByProjectId(Long projectId) {
        List<RequirementPO> requirementPOs = requirementMapper.findByProjectId(projectId);
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    @Override
    public List<Requirement> findByStatus(RequirementStatus status) {
        List<RequirementPO> requirementPOs = requirementMapper.findByStatus(status.name());
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    @Override
    public List<Requirement> findByPriority(RequirementPriority priority) {
        List<RequirementPO> requirementPOs = requirementMapper.findByPriority(priority.name());
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    @Override
    public List<Requirement> findAll() {
        List<RequirementPO> requirementPOs = requirementMapper.findAll();
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    @Override
    public void deleteById(RequirementId requirementId) {
        requirementMapper.deleteById(requirementId.getValue());
    }
    
    @Override
    public boolean existsById(RequirementId requirementId) {
        return requirementMapper.existsById(requirementId.getValue());
    }
    
    @Override
    public boolean hasIncompleteTasks(RequirementId requirementId) {
        return requirementMapper.hasIncompleteTasks(requirementId.getValue());
    }
    
    @Override
    public List<Requirement> findByProjectIdAndStatus(Long projectId, RequirementStatus status) {
        List<RequirementPO> requirementPOs = requirementMapper.findByProjectIdAndStatus(projectId, status.name());
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    @Override
    public List<Requirement> findByOwnerId(String ownerId) {
        List<RequirementPO> requirementPOs = requirementMapper.findByOwnerId(ownerId);
        return requirementPOs.stream().map(this::toRequirement).collect(Collectors.toList());
    }
    
    /**
     * 将领域对象转换为持久化对象
     */
    private RequirementPO toRequirementPO(Requirement requirement) {
        RequirementPO requirementPO = new RequirementPO();
        if (requirement.getId() != null) {
            requirementPO.setId(requirement.getId().getValue());
        }
        requirementPO.setTitle(requirement.getTitle().getValue());
        requirementPO.setDescription(requirement.getDescription() != null ? requirement.getDescription().getValue() : null);
        requirementPO.setStatus(requirement.getStatus().name());
        requirementPO.setPriority(requirement.getPriority().name());
        requirementPO.setOwnerId(requirement.getOwnerId());
        requirementPO.setProjectId(requirement.getProjectId());
        requirementPO.setExpectedCompletionDate(requirement.getExpectedCompletionDate());
        requirementPO.setCreatedAt(requirement.getCreatedAt());
        requirementPO.setUpdatedAt(requirement.getUpdatedAt());
        return requirementPO;
    }
    
    /**
     * 将持久化对象转换为领域对象
     */
    private Requirement toRequirement(RequirementPO requirementPO) {
        return Requirement.restore(
            RequirementId.of(requirementPO.getId()),
            RequirementTitle.of(requirementPO.getTitle()),
            requirementPO.getDescription() != null ? RequirementDescription.of(requirementPO.getDescription()) : null,
            RequirementStatus.valueOf(requirementPO.getStatus()),
            RequirementPriority.valueOf(requirementPO.getPriority()),
            requirementPO.getProjectId(),
            requirementPO.getOwnerId(),
            requirementPO.getExpectedCompletionDate(),
            requirementPO.getCreatedAt(),
            requirementPO.getUpdatedAt()
        );
    }
}